package model

import (
	ryrpc "admin/rpc"
	"common/helper"
	"database/sql"
	"errors"
	"fmt"
	"time"

	"go.mongodb.org/mongo-driver/bson"

	g "github.com/doug-martin/goqu/v9"
	"github.com/doug-martin/goqu/v9/exp"
)

// 站内信
type Message struct {
	ID         string ` db:"id" json:"id" cbor:"id"`
	Title      string `db:"title" json:"title" cbor:"title"`                   //标题
	Content    string `db:"content" json:"content" cbor:"content"`             //内容
	IsTop      int    `db:"is_top" json:"is_top" cbor:"is_top"`                //0不置顶 1置顶
	IsPush     int    `db:"is_push" json:"is_push" cbor:"is_push"`             //0不推送 1推送
	IsVip      int    `db:"is_vip" json:"is_vip" cbor:"is_vip"`                //0非vip站内信 1vip站内信
	Ty         int    `db:"ty" json:"ty" cbor:"ty"`                            //1站内消息 2活动消息
	Level      string `db:"level" json:"level" cbor:"level"`                   //会员等级
	Usernames  string `db:"usernames" json:"usernames" cbor:"usernames"`       //会员账号，多个用逗号分隔
	State      int    `db:"state" json:"state" cbor:"state"`                   //1审核中 2审核通过 3审核拒绝 4已删除
	SendState  int    `db:"send_state" json:"send_state" cbor:"send_state"`    //1未发送 2已发送
	SendName   string `db:"send_name" json:"send_name" cbor:"send_name"`       //发送人名
	SendAt     int64  `db:"send_at" json:"send_at" cbor:"send_at"`             //发送时间
	ApplyAt    uint32 `db:"apply_at" json:"apply_at" cbor:"apply_at"`          //创建时间
	ApplyUid   string `db:"apply_uid" json:"apply_uid" cbor:"apply_uid"`       //创建人uid
	ApplyName  string `db:"apply_name" json:"apply_name" cbor:"apply_name"`    //创建人名
	ReviewAt   uint32 `db:"review_at" json:"review_at" cbor:"review_at"`       //创建时间
	ReviewUid  string `db:"review_uid" json:"review_uid" cbor:"review_uid"`    //创建人uid
	ReviewName string `db:"review_name" json:"review_name" cbor:"review_name"` //创建人名
}

type MessageDbData struct {
	T int64     `json:"total" cbor:"t"`
	S uint      `json:"s" cbor:"s"`
	D []Message `json:"d" cbor:"d"`
}

type MessagesMeiliData struct {
	T int64              `json:"total"`
	S int                `json:"s"`
	D []ryrpc.TblMessage `json:"d"`
}

// MessageInsert  站内信新增
func MessageInsert(record g.Record, sendAt string) error {

	stAt, err := helper.TimeToLoc(sendAt, loc)
	if err != nil {
		return errors.New(helper.DateTimeErr)
	}

	record["send_at"] = stAt
	query, _, _ := dialect.Insert("tbl_messages").Rows(record).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return nil
}

// MessageList  站内信列表
func MessageList(page, pageSize int, sendStartTime, sendEndTime,
	startTime, endTime, reviewStartTime, reviewEndTime string, ex g.Ex) (MessageDbData, error) {

	data := MessageDbData{}
	// 没有查询条件  startTime endTime 必填
	if len(ex) == 0 && (startTime == "" || endTime == "") {
		return data, errors.New(helper.QueryTermsErr)
	}

	if sendStartTime != "" && sendEndTime != "" {

		startAt, err := helper.TimeToLoc(sendStartTime, loc)
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}

		endAt, err := helper.TimeToLoc(sendEndTime, loc)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		if startAt >= endAt {
			return data, errors.New(helper.QueryTimeRangeErr)
		}

		ex["send_at"] = g.Op{"between": exp.NewRangeVal(startAt, endAt)}
	}

	if startTime != "" && endTime != "" {

		startAt, err := helper.TimeToLoc(startTime, loc)
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}

		endAt, err := helper.TimeToLoc(endTime, loc)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		if startAt >= endAt {
			return data, errors.New(helper.QueryTimeRangeErr)
		}

		ex["apply_at"] = g.Op{"between": exp.NewRangeVal(startAt, endAt)}
	}

	if reviewStartTime != "" && reviewEndTime != "" {

		rStart, err := helper.TimeToLoc(reviewStartTime, loc)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		rEnd, err := helper.TimeToLoc(reviewEndTime, loc)
		if err != nil {
			return data, errors.New(helper.TimeTypeErr)
		}

		if rStart >= rEnd {
			return data, errors.New(helper.QueryTimeRangeErr)
		}

		ex["review_at"] = g.Op{"between": exp.NewRangeVal(rStart, rEnd)}
	}

	t := dialect.From("tbl_messages")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	offset := pageSize * (page - 1)
	query, _, _ := t.Select(colsMessage...).Where(ex).
		Offset(uint(offset)).Limit(uint(pageSize)).Order(g.C("apply_at").Desc()).ToSQL()
	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return data, nil
}

// MessageUpdate  站内信更新
func MessageUpdate(id, sendAt string, record g.Record) error {

	ex := g.Ex{
		"id": id,
	}
	data := Message{}
	t := dialect.From("tbl_messages")
	query, _, _ := t.Select(colsMessage...).Where(ex).ToSQL()
	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.RecordNotExistErr)
	}

	if data.State != 1 {
		return errors.New(helper.NoDataUpdate)
	}

	stAt, err := helper.TimeToLoc(sendAt, loc)
	if err != nil {
		return errors.New(helper.DateTimeErr)
	}

	record["send_at"] = stAt
	query, _, _ = dialect.Update("tbl_messages").Set(record).Where(ex).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return nil
}

// MessageReview  站内信审核
func MessageReview(id string, state, flag int, admin map[string]string) error {

	ex := g.Ex{
		"id": id,
	}
	data := Message{}
	query, _, _ := dialect.From("tbl_messages").Select(colsMessage...).Where(ex).ToSQL()
	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return errors.New(helper.RecordNotExistErr)
	}

	if data.State != 1 {
		return errors.New(helper.NoDataUpdate)
	}

	ns := time.Now().Unix()
	// 审核通过时已经超过了发送时间，记录作废
	if ns > data.SendAt && state == 2 {

		record := g.Record{
			"state":       4,
			"review_at":   time.Now().Unix(),
			"review_uid":  admin["id"],
			"review_name": admin["name"],
		}
		query, _, _ = dialect.Update("tbl_messages").Set(record).Where(ex).ToSQL()
		_, err = meta.MerchantDB.Exec(query)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		return errors.New(helper.RecordExpired)
	}

	record := g.Record{
		"state":       state,
		"review_at":   time.Now().Unix(),
		"review_uid":  admin["id"],
		"review_name": admin["name"],
	}
	query, _, _ = dialect.Update("tbl_messages").Set(record).Where(ex).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	// 审核通过
	if state == 2 {

		param := map[string]interface{}{
			"flag":       "1",                            //发送站内信
			"message_id": data.ID,                        //id
			"title":      data.Title,                     //标题
			"content":    data.Content,                   //内容
			"is_top":     fmt.Sprintf("%d", data.IsTop),  //0不置顶 1置顶
			"is_push":    fmt.Sprintf("%d", data.IsPush), //0不推送 1推送
			"is_vip":     fmt.Sprintf("%d", data.IsVip),  //0普通站内信 1vip站内信
			"ty":         fmt.Sprintf("%d", data.Ty),     //1站内消息 2活动消息
			"send_name":  data.SendName,                  //发送人名
		}
		if data.IsVip == 1 {
			param["level"] = data.Level
		} else {
			param["usernames"] = data.Usernames
		}

	}

	return nil
}

// MessageDetail  已发站内信详情
func MessageDetail(id string, page, pageSize int) (MessagesMeiliData, error) {

	data := MessagesMeiliData{
		S: pageSize,
	}

	/*
		ex := g.Ex{
			"id": id,
		}
		var sendState int
		query, _, _ := dialect.From("tbl_messages").Select("send_state").Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&sendState, query)
		if err != nil && err != sql.ErrNoRows {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if err == sql.ErrNoRows || sendState != 2 {
			return data, errors.New(helper.RecordNotExistErr)
		}

		cond := bson.M{
			"message_id": id,
		}

		coll := meta.MgDB.Collection("stb_messages")
		if page >= 1 {
			data.T, err = coll.Find(ctx, cond).Count()
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), "query mongo"), "数据库错误")
			}

			if data.T == 0 {
				return data, nil
			}
		}

		err = coll.Find(ctx, cond).Sort("-ts").Skip(int64((page - 1) * pageSize)).Limit(int64(pageSize)).All(&data.D)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), "query mongodb"), "数据库错误")
		}
	*/
	return data, nil
}

// MessageSystemList  已发站系统内信列表
func MessageSystemList(startTime, endTime string, page, pageSize int, ex bson.M) (MessagesMeiliData, error) {

	data := MessagesMeiliData{
		S: pageSize,
	}
	/*
		startAt, err := helper.TimeToLoc(startTime, loc) // 毫秒级时间戳
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}
		endAt, err := helper.TimeToLoc(endTime, loc) // 毫秒级时间戳
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}

		if startAt >= endAt {
			return data, errors.New(helper.QueryTimeRangeErr)
		}

		ex["send_name"] = "system"
		ex["send_at"] = bson.M{"$gte": startAt, "$lte": endAt}

		coll := meta.MgDB.Collection("stb_messages")
		if page >= 1 {
			data.T, err = coll.Find(ctx, ex).Count()
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), "query mongo"), "数据库错误")
			}

			if data.T == 0 {
				return data, nil
			}
		}

		err = coll.Find(ctx, ex).Sort("-ts").Skip(int64((page - 1) * pageSize)).Limit(int64(pageSize)).All(&data.D)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), "query mongodb"), "数据库错误")
		}
	*/
	return data, nil
}

// MessageDelete  站内信删除
func MessageDelete(id, ids string) error {

	/*
		if ids == "" {
			if !validator.CtypeDigit(id) {
				return errors.New(helper.IDErr)
			}

			ex := g.Ex{
				"id": id,
			}
			record := g.Record{
				"state": 4,
			}
			query, _, _ := dialect.Update("tbl_messages").Set(record).Where(ex).ToSQL()
			_, err := meta.MerchantDB.Exec(query)
			if err != nil {
				return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
			}

			return nil
		}

		var idsM []primitive.ObjectID
		for _, idd := range strings.Split(ids, ",") {
			hex, _ := primitive.ObjectIDFromHex(idd)
			idsM = append(idsM, hex)
		}

		filter := bson.M{
			"_id": bson.M{"$in": idsM},
		}
		coll := meta.MgDB.Collection("stb_messages")
		_, err := coll.RemoveAll(ctx, filter)
		if err != nil {
			return pushLog(fmt.Errorf("%s,[%s]", err.Error(), "del mongo"), "数据库错误")
		}
	*/
	return nil
}

// 发送站内信
func messageSend(msgID, title, subTitle, content, sendName, prefix string, isTop, isVip, ty int, names []string) error {

	/*
		record := g.Record{
			"message_id": msgID,
			"title":      title,
			"content":    content,
			"send_name":  sendName,
			"is_top":     isTop,
			"is_vip":     isVip,
			"is_read":    0,
			"send_at":    time.Now().Unix(),
			"ty":         ty,
		}

		var recordList []interface{}
		for k, v := range names {
			t := time.Now().UnixMicro() + int64(k)
			timeNow := time.UnixMicro(t)
			timeString := timeNow.In(loc).Format("2006-01-02T15:04:05.999999+07:00")
			item := g.Record{
				"message_id": record["message_id"],
				"title":      record["title"],
				"content":    record["content"],
				"send_name":  record["send_name"],
				"is_top":     record["is_top"],
				"is_vip":     record["is_vip"],
				"is_read":    record["is_read"],
				"send_at":    record["send_at"],
				"ty":         record["ty"],
			}
			item["ts"] = timeString
			item["username"] = v
			item["prefix"] = prefix
			recordList = append(recordList, item)
		}
		coll := meta.MgDB.Collection("stb_messages")

		if len(recordList) > 0 {
			pageSize := 200
			page := 1
			if len(recordList) > pageSize {
				for page*pageSize < len(recordList) {
					start := (page - 1) * pageSize
					end := page * pageSize
					pickList := recordList[start:end]
					_, err := coll.InsertMany(ctx, pickList)
					if err != nil {

						return pushLog(fmt.Errorf("%s,[%s]", err.Error(), "del mongo"), "数据库错误")

					}
					page++
				}

				start := (page - 1) * pageSize
				end := len(recordList)
				pickList := recordList[start:end]

				_, err := coll.InsertMany(ctx, pickList)
				if err != nil {

					return pushLog(fmt.Errorf("%s,[%s]", err.Error(), "del mongo"), "数据库错误")

				}
			} else {
				_, err := coll.InsertMany(ctx, recordList)
				if err != nil {

					return pushLog(fmt.Errorf("%s,[%s]", err.Error(), "del mongo"), "数据库错误")

				}
			}
		}
	*/
	return nil
}

func MessageFlushAll() {

	ryrpc.MessageFlushAll()

}
